---
title: Using Resend
description: Learn how to integrate Resend in your Expo and React Native app to programmatically send emails with Expo Router's API Routes.
---

import { Terminal } from '~/ui/components/Snippet';
import { Step } from '~/ui/components/Step';
import { VideoBoxLink } from '~/ui/components/VideoBoxLink';

[Resend](https://resend.com/) is an email API platform designed for developers. It allows you to send, receive, and manage emails programmatically through an API. You can use it to send transactional emails for use cases like newsletters, marketing emails, and more. The API also allows you to set up webhooks for email events, manage domains for deliverability, and receive emails via webhooks.

This guide demonstrates the **essential steps to integrate Resend with your Expo and React Native project**.

<VideoBoxLink videoId="8sPD8SNcUFA" title="How to send emails with Resend from your Expo app" />

## Prerequisites

Before you get started, you need to have the following:

- A project using [Expo Router](/router/installation/)
- An [Expo account](https://expo.dev/signup) to deploy the API route using EAS Hosting
- EAS CLI installed globally (`npm install -g eas-cli`)
- A [Resend account](https://resend.com/)

<Step label="1">

## Create a Resend API key

Go to the [Resend dashboard](https://resend.com/api-keys) > **API Keys** and click on **Create API Key** to generate an API key.

Once you have generated the API key, save it to **.env.local** file in your Expo project:

```shell .env.local
RESEND_API_KEY=YOUR_RESEND_API_KEY
```

> **Note:** Do not commit **.env.local** file to your Version Control System (VCS) like Git. The API key is sensitive and should not be exposed to the public. You must add the file to your **.gitignore** file to ignore it.

</Step>

<Step label="2">

## Install Resend SDK

In your Expo project, install the Resend SDK using the following command:

<Terminal cmd={['$ npx expo install resend']} />

The resend SDK library is a server-only library. It allows you to send emails from the server-side code of your app. Since this guide uses [API Routes](/router/web/api-routes/) to handle email submissions, you need to install the resend as part of your Expo project.

</Step>

<Step label="3">

## Enable and create an API route

To enable using API Routes in your Expo project, you need to set the web.output to server in your [app config](/workflow/configuration/) file:

```json app.json
{
  "web": {
    "output": "server"
  }
}
```

Then, [create an API route](/router/web/api-routes/#create-an-api-route) to handle email submissions. Inside the **app** directory, create a new file called **api/audience+api.ts**. The `+api.ts` extension is used by Expo Router to identify the file as an API Route. To test the integration, you can add the minimal code below to send an email to a recipient using Resend SDK:

```tsx app/api/audience+api.ts
import { Resend } from 'resend';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(request: Request) {
  const body = await request.json();
  const { email } = body;

  if (!email) {
    return Response.json({ success: false });
  }

  await resend.contacts.create({
    email: email,
    // Provide dynamic values on your own
    firstName: 'Steve',
    lastName: 'Wozniak',
    unsubscribed: false,
  });

  return Response.json({ success: true });
}
```

In the above code snippet, the `POST` [request function](/router/web/api-routes/#request-body) is executed when the `/api/audience` route is matched. The function receives a `Request` object as an argument, which contains the HTTP request body. Then, the function extracts the `email` from the request body and sends it to the Resend API to add it to the audience.

</Step>

<Step label="4">

## Add a base URL

To make the API route accessible from your Expo app, you need to add the base URL as an environment variable in your Expo project. Add the following code to your **.env.local** file:

```shell .env.local
EXPO_PUBLIC_BASE_URL=https://example-resend.expo.app # Deployed URL via EAS Hosting
EXPO_PUBLIC_BASE_URL_LOCAL=http://localhost:8081 # Only required for testing locally
```

To test Resend integration locally, you can use `EXPO_PUBLIC_BASE_URL_LOCAL` to point to your local development server, whose URL is provided when you run `npx expo start`. Later in this guide, when you deploy your app to EAS Hosting, ensure to update the `EXPO_PUBLIC_BASE_URL` to the deployed URL.

Note that only variables prefixed with `EXPO_PUBLIC_` can be used in the frontend code, so you can have the above as well as the Resend API key in the same **.env** file, but the `RESEND_API_KEY` will only be accessible from the server-side code (that is, files ending with **+api**).

</Step>

<Step label="5">

## Add a form to your Expo project

The following example code shows a simple form to collect email addresses from app users. In a real-world scenario, you would want to add validation and error handling to the form. For example, the following code is added to the **app/index.tsx** file:

```tsx app/index.tsx
import { useRef, useState } from 'react';
import { Alert, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';

export default function Index() {
  const [email, setEmail] = useState('');
  const inputRef = useRef<TextInput>(null);

  const handleSubmit = async () => {
    if (!email) {
      alert('Email is required.');
      return;
    }

    if (inputRef.current) {
      inputRef.current.blur();
    }

    try {
      const response = await fetch(
        `${process.env.EXPO_PUBLIC_BASE_URL_LOCAL}/api/audience`, // Switch to `EXPO_PUBLIC_BASE_URL` after deploying to EAS Hosting
        {
          method: 'POST',
          body: JSON.stringify({ email }),
        }
      );

      // You can handle other response validations here.

      await response.json();

      Alert.alert('Success', 'Email sent successfully.', [
        {
          text: 'Continue',
        },
      ]);
    } catch (error) {
      alert('Something went wrong.');
      console.error(error);
    }
  };

  return (
    <View style={styles.container}>
      <TextInput
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        ref={inputRef}
        autoCapitalize="none"
        keyboardType="email-address"
        style={styles.input}
      />
      <Pressable style={styles.button} onPress={handleSubmit}>
        <Text style={styles.buttonText}>Send email</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  input: {
    borderWidth: 1,
    borderColor: 'gray',
    padding: 10,
    width: '60%',
    height: '6%',
    borderRadius: 10,
    marginBottom: 10,
    margin: 20,
  },
  button: {
    padding: 10,
    backgroundColor: '#000000',
    borderRadius: 10,
  },
  buttonText: {
    color: 'white',
    textAlign: 'center',
  },
});
```

</Step>

<Step label="6">

## Deploy the API route to EAS Hosting

To make the API route (`/api/audience`) accessible from a URL, you can deploy it to [EAS Hosting](/eas/hosting/get-started/).

1. Run the following command to export the web and API assets. The exported files are saved inside a **dist** directory and the API route file is part of this directory:

<Terminal cmd={['$ npx expo export --platform web']} />

2. Run the following to create a production deployment via EAS Hosting:

<Terminal cmd={['$ eas deploy --prod']} />

The `eas deploy --prod` command will:

- Automatically create an EAS project if you haven't already
- Prompt you to choose the preview URL for your project. Ensure that this URL is the same as the value of `EXPO_PUBLIC_BASE_URL` in your **.env.local** file. This will make the API route accessible from your Expo app while deployed in production

> **Note:** Before deployment, you need to use the `EXPO_PUBLIC_BASE_URL` as your hosted domain in your form screen (**app/index.tsx**).

</Step>

## Learn more about Resend

For more information about Resend's API and usage, see [Resend's official documentation](https://resend.com/docs/introduction).
